<?php

class Core_Model_DbTable_Category_Customs extends Core_Model_DbTable_Category_Abstract
{
	const TABLE_NAME                = 'custom_categories';
	protected $_name				= self::TABLE_NAME;
    protected $_rowClass            = 'Core_Model_Category_Custom';
	protected $_referenceMap    = array(
        'Store' => array(
            'columns'           => 'id_store',
            'refTableClass'     => 'Core_Model_DbTable_Stores',
            'refColumns'        => 'id'
        ),
    );
	private static $_instance;
	
	/**
	 *
	 * @return Core_Model_DbTable_Category_Customs 
	 */
	public static function getInstance()
	{
		if (is_null(self::$_instance))
		{
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	
	public function getCategoryByPath($path)
	{
		$select = $this->select()->where('path = ?', $path);
		return $this->fetchRow($select);
	}
	
	/**
	 * @param int $id_store 
	 * @return Zend_Db_Table_Rowset
	 */
	public function getAllCategoriesByIdStore($id_store, $form_cache = true)
	{
		$rowSet = null;
		if( !$form_cache )
		{
			$rowSet =  $this->_getAllCategories($id_store);
		}
		else
		{
			$key	= Core_Cache_IKeys::ALL_CATEGORIES_BY_STORE . '_' . $id_store;
			$data	= YouNet_Util::getObjectMemCache()->load($key);			
			if( $data === false)
			{
				$rowSet =  $this->_getAllCategories($id_store);
				YouNet_Util::getObjectMemCache()->save($rowSet->toArray(),$key);			
			}
			else
			{
				$rawData  = array(
					'table'    => $this,
					'data'     => $data,
					'readOnly' => true,
					'rowClass' => $this->getRowClass(),
					'stored'   => true
				);
				$rowsetClass	= $this->getRowsetClass();
				$rowSet			= new $rowsetClass($rawData);
			}
		}
		return $rowSet;
	}
	
	public function _getAllCategories($id_store)
	{
		return $this->fetchAll(
			array(
				'id_store = ?' => $id_store
			),
			array(
				'z_order ASC'
			)
		);
	}
	/**
	 *
	 * @param int $id_store
	 * @param int $id_parent 
	 * @return Zend_Db_Table_Rowset
	 */
	public function getListByIdStore($id_store, $id_parent = NULL)
	{
		$select = $this->select()->where('id_store = ?', $id_store);
		if( $id_parent !==  NULL)
		{
			$select->where('id_parent = ?', $id_parent);
		}
		else
		{
			$select->where('id_parent IS NULL');
		}
        $select->order('name ASC');
		return $this->fetchAll($select);
	}
	
	public function updateByIdStore(array $data, $id_category, $id_store)
	{
		return $this->update(
			$data,
			array(
				'id = ?' => $id_category,
				'id_store = ?' => $id_store
			)
		);
	}
	
	/**
	 *
	 * @param int $id_category
	 * @param int $id_store
	 * @return Core_Model_Category
	 */
	public function fineOneByIdStore($id_category, $id_store)
	{
		return $this->fetchRow(array(
			'id = ?'		=> $id_category,
			'id_store = ?'	=> $id_store
		));
	}
	
	public function deleteByIdStore($id_category, $id_store)
	{
		return $this->delete(
			array(
				'id = ?'		=> $id_category,
				'id_store = ?'	=> $id_store
			)
		);
	}
	
	public function getCategoryTreeOfProduct($arrayIds)
	{
		$select = $this->select()->where('id IN (?)', $arrayIds)->order('path');
		return $this->fetchAll($select);
	}
	
	public function getCategoryListByPath($path)
	{
		$path = str_replace('%', '', $path);
		$arrCategoryIds = explode(Core_Model_DbTable_Category_Abstract::DELIMITER, $path);
		return $this->getCategoryTreeOfProduct($arrCategoryIds);
	}
	
	public function getNumberOfActiveProduct($id_store)
	{
		$query = $this->select()
				->from($this, array('sum(number_active_products) as total_number_active_products'))
				->where('id_store=?', $id_store);
		$result = $this->fetchAll($query)->current();
		if (empty($result->total_number_active_products))
		{
			return 0;
		}
		return $result->total_number_active_products;
	}
	
	public function getNumberOfTotalProduct($id_store)
	{
		$query = $this->select()
				->from($this, array('sum(number_products) as total_number_products'))
				->where('id_store=?', $id_store);
		$result = $this->fetchAll($query)->current();
		if (empty($result->total_number_products))
		{
			return 0;
		}
		return $result->total_number_products;
	}
	
	public function moveCategoryByIdStore($id_category, $id_store, $id_category_parent = NULL, $id_above = NULL)
	{
		$currentCategory	= $this->fineOneByIdStore($id_category, $id_store);
		if( !$currentCategory )
		{
			return false;
		}
		
		$newparentPath			= '';
		if( !empty($id_category_parent) )
		{
			$parentCategory	= $this->fineOneByIdStore($id_category_parent, $id_store);
			if( !$parentCategory )
			{
				return false;
			}
			$newparentPath		= $parentCategory->path;
		}
		
		try{
			$this->getAdapter()->beginTransaction();
			
			if( $id_category_parent )
			{
				$currentCategory->id_parent = $id_category_parent;
			}
			else
			{
				$currentCategory->id_parent = NULL;
			}
			//Update Z Order
			if( $id_above )
			{
				$aboveCategory				= $this->fineOneByIdStore($id_above, $id_store);
				if( $aboveCategory )
				{
					$currentCategory->z_order	= $aboveCategory->z_order;
					//Update others Z Order
					$where = array();
					$where['z_order >= ?'] = $aboveCategory->z_order;
					if( $id_category_parent && ($id_category_parent != $id_category) )
					{
						$where['id_parent = ?'] = $id_category_parent;
					}
					else
					{
						$where['id_parent ?'] = new Zend_Db_Expr('IS NULL');
					}
					$where['id_store = ?'] = $id_store;

					$this->update(
						array(
							'z_order' => new Zend_Db_Expr('z_order + 1')
						),
						$where
					);
				}
			}
			else
			{
				$currentCategory->z_order	= $this->findNewZIndex($id_store, $currentCategory->id_parent);
			}
			$currentCategory->save();
			
			$currentParentPath 	= $currentCategory->path;
			$newparentPath 		= $newparentPath.$currentCategory->id.'-';
			$this->update(
				array('path'		=> new Zend_Db_Expr("REPLACE(path,'$currentParentPath','$newparentPath')")),
				array('path LIKE ?' => $currentCategory->path.'%')
			);
			
			$this->getAdapter()->commit();
		}
		catch(Exception $ex)
		{
			$this->getAdapter()->rollBack();
			return false;
		}
		return true;
	}
	
	public function findNewZIndex($id_store, $id_parent = NULL)
	{
		$select = $this
			->select()
			->from(self::TABLE_NAME,array(
				'max_z_order' => new Zend_Db_Expr('MAX(z_order)')
			));
		if( $id_parent )
		{
			$select->where('id_parent = ?', $id_parent);
		}
		else
		{
			$select->where('id_parent IS NULL');
		}
		$select->where('id_store = ?', $id_store);
		$returnValue = $select->query()->fetchColumn();
		return $returnValue + 1;
	}
}